#include "db.h"
#include "protocol.h"
#include <sqlite3.h>
#include <string.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <gmssl/sm3.h>
#include "../include/auth/sm3_auth.h"

#define SALT_LENGTH 16

typedef struct
{
    char username[32];
    unsigned char salt[SALT_LENGTH];
    unsigned char hash[SM3_DIGEST_LENGTH];
} UserAuth;

// 计算SM3哈希
void calculate_sm3_hash(const char *password, const unsigned char *salt, unsigned char *hash)
{
    SM3_CTX ctx;
    sm3_init(&ctx);
    sm3_update(&ctx, salt, SALT_LENGTH);
    sm3_update(&ctx, (const uint8_t *)password, strlen(password));
    sm3_finish(&ctx, hash);
}

// 用户注册
/**
 * @brief 注册新用户并存储安全凭证
 * @param db 数据库连接指针
 * @param username 用户名(长度4-20字符)
 * @param password 明文密码(需满足复杂度要求)
 * @return 成功返回0，失败返回错误代码：
 *         -1 用户已存在
 *         -2 数据库操作失败
 *         -3 内存分配失败
 * @details 使用SM3哈希算法结合随机盐值存储密码，采用PBKDF2密钥派生迭代5000次
 */
/**
 * @brief 用户注册函数
 * @param db 数据库连接句柄
 * @param username 用户名（长度3-20字符）
 * @param password 明文密码（长度6-32字符）
 * @return 0成功，-1参数错误，-2数据库错误
 * @details 密码存储格式：PBKDF2-HMAC-SHA256(迭代次数5000)
 * @throws SQLITE_CONSTRAINT 用户名重复
 */
int user_register(sqlite3 *db, const char *username, const char *password)
{
    UserAuth user;
    generate_auth_salt(user.salt, SALT_LENGTH);
    calculate_sm3_hash(password, user.salt, user.hash);

    char *sql = "INSERT INTO users (username, salt, password_hash) VALUES (?, ?, ?)";
    sqlite3_stmt *stmt;

    if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK)
    {
        return -1;
    }

    sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC);
    sqlite3_bind_blob(stmt, 2, user.salt, SALT_LENGTH, SQLITE_STATIC);
    sqlite3_bind_blob(stmt, 3, user.hash, SM3_DIGEST_LENGTH, SQLITE_STATIC);

    int result = sqlite3_step(stmt);
    sqlite3_finalize(stmt);

    if (result == SQLITE_DONE)
    {
        int new_user_id = sqlite3_last_insert_rowid(db);
        if (new_user_id > 0)
        {
            // 为新用户授予对根路径 "/" 的默认权限 (读, 写, 删除)
            if (add_file_permission(db, new_user_id, "/", 1, 1, 1) != 0)
            {
                fprintf(stderr, "[DB user_register] Critical: Failed to add default root permission (r/w/d) for user_id %d. User will likely face permission issues.\n", new_user_id);
                // 考虑此处是否应返回错误，因为没有权限用户也无法正常使用。
                // 但为保持与之前逻辑一致（即使add_user中权限失败也返回0），暂时仅打印错误。
            }
            else
            {
                fprintf(stdout, "[DB user_register] Default root permissions (r/w/d) granted to user_id %d for path '/'.\n", new_user_id);
            }
        }
        else
        {
            fprintf(stderr, "[DB user_register] Critical: Failed to get new_user_id after insert for user '%s'. Cannot grant default permissions.\n", username);
            // 这也是一个严重问题，因为无法设置权限。
        }
        return 0; // 用户注册成功
    }
    else
    {
        // 记录更详细的SQLite错误信息
        fprintf(stderr, "[DB user_register] Failed to insert user '%s'. SQLite error: %s (SQLite error code: %d, extended code: %d)\n",
                username, sqlite3_errmsg(db), sqlite3_errcode(db), sqlite3_extended_errcode(db));
        return -1; // 用户注册失败 (例如，用户已存在或数据库约束冲突)
    }
}

// 添加新用户 (修改为接受预计算的哈希和盐值)
int add_user(sqlite3 *db,
             const char *username,
             const unsigned char *password_hash, // 来自客户端的、已加盐的密码哈希
             const unsigned char *salt,          // 来自客户端的盐值
             int salt_len,                       // 盐值长度 (应为 SALT_LENGTH)
             int hash_len,                       // 哈希长度 (应为 SM3_DIGEST_LENGTH)
             int permission_level)
{
    if (!db || !username || !password_hash || !salt || salt_len != SALT_LENGTH || hash_len != SM3_DIGEST_LENGTH)
    {
        fprintf(stderr, "[DB add_user] Invalid parameters. salt_len=%d (exp %d), hash_len=%d (exp %d)\n",
                salt_len, SALT_LENGTH, hash_len, SM3_DIGEST_LENGTH);
        return -1; // 参数错误
    }

    // 检查用户名是否已存在
    sqlite3_stmt *stmt;
    const char *sql_check = "SELECT id FROM users WHERE username = ?;";
    int result;

    if (sqlite3_prepare_v2(db, sql_check, -1, &stmt, NULL) != SQLITE_OK)
    {
        fprintf(stderr, "[DB add_user] 准备检查用户名SQL失败: %s\n", sqlite3_errmsg(db));
        return -2; // 数据库错误
    }
    sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC);
    result = sqlite3_step(stmt);
    sqlite3_finalize(stmt);

    if (result == SQLITE_ROW)
    {
        fprintf(stderr, "[DB add_user] 用户名 '%s' 已存在.\n", username);
        return -3; // 用户已存在
    }
    if (result != SQLITE_DONE)
    { // SQLITE_DONE表示没有找到行，这是我们期望的
        fprintf(stderr, "[DB add_user] 检查用户名时sqlite3_step返回意外结果: %d\n", result);
        return -2; // 数据库错误
    }

    // 将用户信息保存到数据库
    // salt 和 password_hash 由调用者（服务器的注册逻辑）提供，它们来自客户端
    const char *sql_insert =
        "INSERT INTO users (username, salt, password_hash, permission_level) "
        "VALUES (?, ?, ?, ?);";

    if (sqlite3_prepare_v2(db, sql_insert, -1, &stmt, NULL) != SQLITE_OK)
    {
        fprintf(stderr, "[DB add_user] 准备插入用户SQL失败: %s\n", sqlite3_errmsg(db));
        return -2; // 数据库错误
    }

    sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC);
    sqlite3_bind_blob(stmt, 2, salt, SALT_LENGTH, SQLITE_STATIC);                // 使用传入的盐值
    sqlite3_bind_blob(stmt, 3, password_hash, SM3_DIGEST_LENGTH, SQLITE_STATIC); // 使用传入的哈希
    sqlite3_bind_int(stmt, 4, permission_level);

    result = sqlite3_step(stmt);
    sqlite3_finalize(stmt);

    if (result != SQLITE_DONE)
    {
        fprintf(stderr, "[DB add_user] 插入用户失败: %s (sqlite_step result: %d)\n", sqlite3_errmsg(db), result);
        return -2; // 数据库错误
    }

    // 添加默认文件夹权限
    int new_user_id = sqlite3_last_insert_rowid(db);
    if (new_user_id > 0)
    {
        // Grant default permissions to root path "/"
        // Arguments: db, user_id, path, can_read, can_write, can_delete
        if (add_file_permission(db, new_user_id, "/", 1, 1, 1) != 0) // Grant R/W/D
        {
            fprintf(stderr, "[DB add_user] Failed to add default root permission (r/w/d) for user_id %d\n", new_user_id);
        }
        else
        {
            fprintf(stdout, "[DB add_user] Default root permissions (r/w/d) granted to user_id %d.\n", new_user_id);
        }
    }
    else
    {
        fprintf(stderr, "[DB add_user] Failed to get new_user_id after insert for user '%s'\n", username);
    }

    // fprintf(stdout, "[DB add_user] 用户 '%s' 添加成功.\n", username);
    return 0; // 成功
}

// 用户认证
int authenticate_user(sqlite3 *db, const char *username, const char *password)
{
    fprintf(stdout, "服务端：用户 '%s' 尝试登录认证...\n", username);
    if (!db || !username || !password)
    {
        fprintf(stderr, "[AUTH_DEBUG] authenticate_user: Invalid parameters.\n");
        return -1;
    }
    // fprintf(stdout, "[AUTH_DEBUG] Authenticating user: %s\n", username); // 打印尝试认证的用户名

    sqlite3_stmt *stmt;
    const char *sql =
        "SELECT id, salt, password_hash FROM users WHERE username = ?;";

    if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK)
    {
        fprintf(stderr, "[AUTH_DEBUG] sqlite3_prepare_v2 failed: %s\n", sqlite3_errmsg(db));
        return -1;
    }

    sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC);
    int result = sqlite3_step(stmt);

    if (result != SQLITE_ROW)
    {
        fprintf(stderr, "[AUTH_DEBUG] User '%s' not found in database.\n", username);
        fprintf(stdout, "服务端：数据库中未找到用户 '%s'。\n", username);
        sqlite3_finalize(stmt);
        return -1;
    }

    fprintf(stdout, "服务端：从数据库获取用户 '%s' 的盐值和存储的SM3哈希值。\n", username);
    int user_id = sqlite3_column_int(stmt, 0);
    const unsigned char *salt = sqlite3_column_blob(stmt, 1);
    int salt_len = sqlite3_column_bytes(stmt, 1);
    const unsigned char *stored_hash_ptr = sqlite3_column_blob(stmt, 2);
    int hash_len = sqlite3_column_bytes(stmt, 2);

    // Buffer to hold a local copy of the stored hash
    unsigned char actual_stored_hash_bytes[SM3_DIGEST_LENGTH];

    // 打印从数据库获取的盐值和哈希值 (Hex格式)
    char salt_hex[SALT_LENGTH * 2 + 1] = {0};
    char stored_hash_hex[SM3_DIGEST_LENGTH * 2 + 1] = {0};

    if (salt_len > 0 && salt)
    { // Check if salt is not NULL and length is positive
        for (int i = 0; i < salt_len; ++i)
            sprintf(salt_hex + i * 2, "%02x", salt[i]);
    }
    fprintf(stdout, "[AUTH_DEBUG] DB Salt for %s (len %d): %s\n", username, salt_len, salt_hex);

    if (hash_len > 0 && stored_hash_ptr)
    { // Check if stored_hash_ptr is not NULL
        // Copy the hash from SQLite's memory before it might be finalized
        if (hash_len == SM3_DIGEST_LENGTH)
        { // Ensure we don't read out of bounds if hash_len is somehow wrong
            memcpy(actual_stored_hash_bytes, stored_hash_ptr, SM3_DIGEST_LENGTH);
            for (int i = 0; i < SM3_DIGEST_LENGTH; ++i)
                sprintf(stored_hash_hex + i * 2, "%02x", actual_stored_hash_bytes[i]); // Use the copy for hex string generation too
        }
        else
        {
            fprintf(stderr, "[AUTH_DEBUG] Warning: hash_len (%d) from DB does not match SM3_DIGEST_LENGTH (%d). Will not copy or use for hex.\n", hash_len, SM3_DIGEST_LENGTH);
        }
    }
    fprintf(stdout, "[AUTH_DEBUG] DB Stored Hash for %s (len %d): %s\n", username, hash_len, stored_hash_hex);

    if (salt_len != SALT_LENGTH || hash_len != SM3_DIGEST_LENGTH)
    {
        fprintf(stderr, "[AUTH_DEBUG] Salt/Hash length mismatch. DB Salt_len: %d (expected %d), DB Hash_len: %d (expected %d)\n", salt_len, SALT_LENGTH, hash_len, SM3_DIGEST_LENGTH);
        sqlite3_finalize(stmt);
        return -1;
    }

    // Now that we have copied the hash, we can finalize the statement earlier if needed,
    // though it's fine here as well as long as salt pointer is also handled if used after finalize.
    // For safety, let's assume salt pointer also might become invalid after finalize, though less common for bind_text.
    // We'll make a copy of salt too if we were to use it after finalize, but sm3_hash_password uses `salt` pointer before finalize.

    unsigned char computed_hash[SM3_DIGEST_LENGTH];
    fprintf(stdout, "服务端：准备使用SM3算法计算用户 '%s' 输入密码的哈希值（加盐）。\n", username);
    if (sm3_hash_password(password, salt, salt_len, computed_hash, SM3_DIGEST_LENGTH) < 0)
    {
        fprintf(stderr, "[AUTH_DEBUG] sm3_hash_password computation failed.\n");
        fprintf(stdout, "服务端：SM3哈希计算失败，用户 '%s' 认证失败。\n", username);
        sqlite3_finalize(stmt);
        return -1;
    }

    sqlite3_finalize(stmt); // Finalize statement as early as possible once its data is retrieved or copied.

    // 打印计算出的哈希值 (Hex格式)
    char computed_hash_hex[SM3_DIGEST_LENGTH * 2 + 1] = {0};
    for (int i = 0; i < SM3_DIGEST_LENGTH; ++i)
        sprintf(computed_hash_hex + i * 2, "%02x", computed_hash[i]);
    fprintf(stdout, "[AUTH_DEBUG] Computed Hash for %s (password: '%s'): %s\n", username, password, computed_hash_hex);

    // 比较哈希值 using the local copy of the stored hash
    int hashes_match = 1;
    for (int i = 0; i < SM3_DIGEST_LENGTH; i++)
    {
        if (computed_hash[i] != actual_stored_hash_bytes[i]) // Use the copied hash bytes
        {
            hashes_match = 0;
            fprintf(stdout, "[AUTH_DEBUG] Hash mismatch at byte %d. DB_COPY: %02x, Computed: %02x\n", i, actual_stored_hash_bytes[i], computed_hash[i]);
        }
    }

    if (!hashes_match)
    {
        fprintf(stdout, "[AUTH_DEBUG] Hashes do NOT match for user %s.\n", username);
        fprintf(stdout, "服务端：SM3哈希值不匹配，用户 '%s' 认证失败。\n", username);
        return -1;
    }

    fprintf(stdout, "[AUTH_DEBUG] Hashes MATCH for user %s. Authentication successful.\n", username);
    fprintf(stdout, "服务端：SM3哈希值匹配，用户 '%s' 认证成功。\n", username);
    add_audit_log(db, user_id, "LOGIN", NULL, ERR_SUCCESS);

    return user_id;
}

// 获取用户ID
int get_user_id(sqlite3 *db, const char *username)
{
    if (!db || !username)
    {
        return -1;
    }

    sqlite3_stmt *stmt;
    const char *sql = "SELECT id FROM users WHERE username = ?;";

    if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK)
    {
        return -1;
    }

    sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC);
    int result = sqlite3_step(stmt);

    if (result != SQLITE_ROW)
    {
        // 用户不存在
        sqlite3_finalize(stmt);
        return -1;
    }

    int user_id = sqlite3_column_int(stmt, 0);
    sqlite3_finalize(stmt);

    return user_id;
}

// 获取用户权限级别
int get_user_permission_level(sqlite3 *db, int user_id)
{
    if (!db || user_id <= 0)
    {
        return -1;
    }

    sqlite3_stmt *stmt;
    const char *sql = "SELECT permission_level FROM users WHERE id = ?;";

    if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK)
    {
        return -1;
    }

    sqlite3_bind_int(stmt, 1, user_id);
    int result = sqlite3_step(stmt);

    if (result != SQLITE_ROW)
    {
        // 用户不存在
        sqlite3_finalize(stmt);
        return -1;
    }

    int permission_level = sqlite3_column_int(stmt, 0);
    sqlite3_finalize(stmt);

    return permission_level;
}